import axios, { AxiosRequestConfig } from "axios";
import storage from "./storageManage";
import { confirmLogin } from "@/components/GlobalModal";

// const {get} = storage

// 定义实例时所需要的参数
interface SetConfig {
  needToken?: boolean;
  showLoading?: boolean;
  handlerStatus?: boolean;
}

// 默认的用户调用参数配置
let defaultConfig: SetConfig = {
  needToken: true, // 是否需要token
  showLoading: false, // 是否需要统一显示loading
  handlerStatus: true, // 是否统一处理错误
};

const config = {
  timeout: 3000, // 请求3000没有反应就会超时
};

// 使用配置的config创建一个axios实例
const instance = axios.create(config);

// 为实例对象添加请求拦截
// 两个参数一个是成功，一个是实败
instance.interceptors.request.use(
  function (config) {
    // 在发送请求之前做些什么
    // 检查是否需要token,如果需要检查token
    if (defaultConfig.needToken) {
      // 检查是否有token, 如果需要且没有token,
      const token = storage.get("token");
      // token有效，配置token并往下走
      if (token) {
        config.headers["Authori-zation"] = `Bearer ${token}`;
      }
      // 没有token,跳转到登陆页
      else {
        confirmLogin(["您的登陆信息已失效，请重新登陆"], function () {
          window.location.href = "/login";
        });
        return;
      }
      // token有效，发起请求
    } else {
      // 直接请求
    }
    return config;
  },
  function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么
    // 在axios实例的响应拦截器里，一般只判断状态码是否是200
    // 请求成功
    if (response.status === 200) {
      return response.data;
    }

    // 401 表示授权失败
    if (response.status === 401) {
      window.location.href = "/login";
      return;
    }

    console.log("请求错误了", response);
    return response;
  },
  function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  }
);

/**
 * 针对单个请求的处理、拦截
 * config 需要的参数有：url, methondType, 如果get类型的需要以params方式传参，如果是post类型的，需要以data方式传参
 * @param config
 * @returns
 */
function request(config: AxiosRequestConfig, setConfig?: SetConfig) {
  if (setConfig) {
    // 如果调用时有不同的配置，修改默认配置
    defaultConfig = { ...defaultConfig, ...setConfig };
  }
  // 使用promise再一次封装，避免实例返回的不是一个promise对象
  return new Promise((resolve, reject) => {
    // 调用axios实例的request方法
    instance
      .request(config)
      // 因为在上面的拦截器做了所有的状态判断，所以这边只要是正常返回了，就都是成功请求，直接调用resolve将结果返回
      .then((res) => {
        resolve(res);
      })
      // 错误
      .catch((err) => {
        reject(err);
      });
  });
}

/**
 * 向外暴露的简易方法
 * 调用时需要传入返回类型
 * @param url
 * @param config
 * @returns
 */
export function post(url: string, data: any, config?: SetConfig) {
  return request({ data, url, method: "POST" }, config);
}
export function put(url: string, data: any, config?: SetConfig) {
  return request({ data, url, method: "PUT" }, config);
}

export function get(url: string, data: any, config?: SetConfig) {
  return request({ params: data, url, method: "GET" }, config);
}
export function del(url: string, data: any, config?: SetConfig) {
  return request({ params: data, url, method: "DELETE" }, config);
}
